import TcpSocket from "react-native-tcp-socket";
import Emitter from "./Emitter.ts";

class TcpServer extends Emitter {
    private server: TcpSocket.Server | undefined | null;
    private serverSocket: TcpSocket.Socket | undefined | null;
    private heartbeatTimer: NodeJS.Timeout | null | undefined;
    private isManualClose = false;

    constructor() {
        super();
    }

    start() {
        this.stop();
        this.server = TcpSocket.createServer((socket) => {
            console.log('client_connected', socket.address());
            this.serverSocket?.destroy();
            this.emit('client_connected', socket.address());
            socket.on('data', (data) => {
                const str = data.toString();
                if (str !== '__ping__') {
                    this.emit('data', data);
                } else {
                    this.send('__pong__');
                }
            });
            socket.on('error', (err) => {
                this.emit('error', err);
            });
            socket.on('close', () => {
                this.serverSocket = null;
                this.emit('client_disconnected');
                if (!this.isManualClose) {
                    setTimeout(() => {
                        this.start();
                    }, 3000);
                }
            });
            socket.on('timeout', () => {
                this.emit('timeout');
            });
            this.serverSocket = socket;
        }).listen({port: 12345, host: '0.0.0.0'}, () => {
            this.emit('server:ready', {port: 12345});
        });

        this.server.on('error', (err) => {
            console.warn('A server error:', err);
            this.emit('Server error', err);
        });

        this.server.on('close', () => {
            console.log('Server closed');
            this.emit('Server closed');
        });
    }

    stop() {
        this.isManualClose = true;
        this.stopHeartbeat();
        this.serverSocket?.destroy();
        this.server?.close();
        this.serverSocket = null;
        this.server = null;
    }

    send(data: string) {
        if (this.serverSocket && !this.serverSocket.destroyed) {
            this.serverSocket?.write(data);
        }
    }

    private sendHeartbeat() {
        this.heartbeatTimer = setInterval(() => {
            this.send('__pong__');
        }, 3000);
    }

    private stopHeartbeat() {
        if (this.heartbeatTimer) {
            clearInterval(this.heartbeatTimer);
            this.heartbeatTimer = null;
        }
    }
}

export default TcpServer;
